#ifndef __WM8978_H__
#define __WM8978_H__


/** @defgroup SPI_I2S_Standard 
  * @{
  */

#define I2S_Standard_Phillips           ((uint16_t)0x0000)
#define I2S_Standard_MSB                ((uint16_t)0x0010)
#define I2S_Standard_LSB                ((uint16_t)0x0020)
#define I2S_Standard_PCMShort           ((uint16_t)0x0030)
#define I2S_Standard_PCMLong            ((uint16_t)0x00B0)
#define IS_I2S_STANDARD(STANDARD) (((STANDARD) == I2S_Standard_Phillips) || \
                                   ((STANDARD) == I2S_Standard_MSB) || \
                                   ((STANDARD) == I2S_Standard_LSB) || \
                                   ((STANDARD) == I2S_Standard_PCMShort) || \
                                   ((STANDARD) == I2S_Standard_PCMLong))
/**
  * @}
  */
  
/** @defgroup SPI_I2S_Data_Format 
  * @{
  */

#define I2S_DataFormat_16b              ((uint16_t)0x0000)
#define I2S_DataFormat_16bextended      ((uint16_t)0x0001)
#define I2S_DataFormat_24b              ((uint16_t)0x0003)
#define I2S_DataFormat_32b              ((uint16_t)0x0005)
#define IS_I2S_DATA_FORMAT(FORMAT) (((FORMAT) == I2S_DataFormat_16b) || \
                                    ((FORMAT) == I2S_DataFormat_16bextended) || \
                                    ((FORMAT) == I2S_DataFormat_24b) || \
                                    ((FORMAT) == I2S_DataFormat_32b))

/*
 * Register values.
 */
#define WM8978_RESET						0x00
#define WM8978_POWER_MANAGEMENT_1			0x01
#define WM8978_POWER_MANAGEMENT_2			0x02
#define WM8978_POWER_MANAGEMENT_3			0x03
#define WM8978_AUDIO_INTERFACE				0x04
#define WM8978_COMPANDING_CONTROL			0x05
#define WM8978_CLOCKING						0x06
#define WM8978_ADDITIONAL_CONTROL			0x07
#define WM8978_GPIO_CONTROL					0x08
#define WM8978_JACK_DETECT_CONTROL_1		0x09
#define WM8978_DAC_CONTROL					0x0A
#define WM8978_LEFT_DAC_DIGITAL_VOLUME		0x0B
#define WM8978_RIGHT_DAC_DIGITAL_VOLUME		0x0C
#define WM8978_JACK_DETECT_CONTROL_2		0x0D
#define WM8978_ADC_CONTROL					0x0E
#define WM8978_LEFT_ADC_DIGITAL_VOLUME		0x0F
#define WM8978_RIGHT_ADC_DIGITAL_VOLUME		0x10
#define WM8978_EQ1							0x12
#define WM8978_EQ2							0x13
#define WM8978_EQ3							0x14
#define WM8978_EQ4							0x15
#define WM8978_EQ5							0x16
#define WM8978_DAC_LIMITER_1				0x18
#define WM8978_DAC_LIMITER_2				0x19
#define WM8978_NOTCH_FILTER_1				0x1b
#define WM8978_NOTCH_FILTER_2				0x1c
#define WM8978_NOTCH_FILTER_3				0x1d
#define WM8978_NOTCH_FILTER_4				0x1e
#define WM8978_ALC_CONTROL_1				0x20
#define WM8978_ALC_CONTROL_2				0x21
#define WM8978_ALC_CONTROL_3				0x22
#define WM8978_NOISE_GATE					0x23
#define WM8978_PLL_N						0x24
#define WM8978_PLL_K1						0x25
#define WM8978_PLL_K2						0x26
#define WM8978_PLL_K3						0x27
#define WM8978_3D_CONTROL					0x29
#define WM8978_BEEP_CONTROL					0x2b
#define WM8978_INPUT_CONTROL				0x2c
#define WM8978_LEFT_INP_PGA_CONTROL			0x2d
#define WM8978_RIGHT_INP_PGA_CONTROL		0x2e
#define WM8978_LEFT_ADC_BOOST_CONTROL		0x2f
#define WM8978_RIGHT_ADC_BOOST_CONTROL		0x30
#define WM8978_OUTPUT_CONTROL				0x31
#define WM8978_LEFT_MIXER_CONTROL			0x32
#define WM8978_RIGHT_MIXER_CONTROL			0x33
#define WM8978_LOUT1_HP_CONTROL				0x34
#define WM8978_ROUT1_HP_CONTROL				0x35
#define WM8978_LOUT2_SPK_CONTROL			0x36
#define WM8978_ROUT2_SPK_CONTROL			0x37
#define WM8978_OUT3_MIXER_CONTROL			0x38
#define WM8978_OUT4_MIXER_CONTROL			0x39

#define WM8978_CACHEREGNUM					58

/* 定义最大音量 */
#define VOLUME_MAX		                    63		/* 最大音量 */
/* 定义最大MIC增益 */
#define GAIN_MAX		                    63		/* 最大增益 */

/* WM8978 音频输入通道控制选项, 可以选择多路，比如 MIC_LEFT_ON | LINE_ON */
typedef enum
{
	IN_PATH_OFF		= 0x00,	/* 无输入 */
	MIC_LEFT_ON 	= 0x01,	/* LIN,LIP脚，MIC左声道（接板载咪头）  */
	MIC_RIGHT_ON	= 0x02,	/* RIN,RIP脚，MIC右声道（接板载咪头）  */
	LINE_ON			= 0x04, /* L2,R2 立体声输入(接板载耳机插座) */
	AUX_ON			= 0x08,	/* AUXL,AUXR 立体声输入（开发板没用到） */
	DAC_ON			= 0x10,	/* I2S数据DAC (CPU产生音频信号) */
	ADC_ON			= 0x20	/* 输入的音频馈入WM8978内部ADC （I2S录音) */
}IN_PATH_E;

/* WM8978 音频输出通道控制选项, 可以选择多路 */
typedef enum
{
	OUT_PATH_OFF	= 0x00,	/* 无输出 */
	EAR_LEFT_ON 	= 0x01,	/* LOUT1 耳机左声道(接板载耳机插座) */
	EAR_RIGHT_ON	= 0x02,	/* ROUT1 耳机右声道(接板载耳机插座) */
	SPK_ON			= 0x04,	/* LOUT2和ROUT2反相输出单声道（开发板没用到）*/
	OUT3_4_ON		= 0x08,	/* OUT3 和 OUT4 输出单声道音频（开发板没用到）*/
}OUT_PATH_E;

/**********************************R1: WM8978_POWER_MANAGEMENT_1*****************************************/

/* Reference string impedance to VMID pin */
#define WM8978_R1_VMIDSEL_OFF					(0 << 0)
#define WM8978_R1_VMIDSEL_75K					(1 << 0)
#define WM8978_R1_VMIDSEL_300K					(2 << 0)
#define WM8978_R1_VMIDSEL_5K					(3 << 0)

/* Analogue amplifier bias control */
#define WM8978_R1_BIAS_ENABLE					(1 << 3)

/* OUT3 or OUT4 mixer enable */
#define WM8978_R1_OUT3_MIX_ENABLE				(1 << 6)
#define WM8978_R1_OUT4_MIX_ENABLE				(1 << 7)

/**********************************R2: WM8978_POWER_MANAGEMENT_2*****************************************/

/* Enable ADC left or right channel */
#define WM8978_R2_LEFT_ADC_ENABLE				(1 << 0)
#define WM8978_R2_RIGHT_ADC_ENABLE				(1 << 1)

/* Left or Right channel input PGA enable */
#define WM8978_R2_LEFT_INPUT_PGA_ENABLE			(1 << 2)
#define WM8978_R2_RIGHT_INPUT_PGA_ENABLE		(1 << 3)

/* Left or Right channel Input BOOST enable */
#define WM8978_R2_LEFT_INPUT_BOOST_ENABLE		(1 << 4)
#define WM8978_R2_RIGHT_INPUT_BOOST_ENABLE		(1 << 5)

/* LOUT1 or ROUT1 output enable */
#define WM8978_R2_LOUT1_ENABLE					(1 << 7)
#define WM8978_R2_ROUT1_ENABLE					(1 << 8)

/**********************************R3: WM8978_POWER_MANAGEMENT_3*****************************************/

/* Left or Right channel DAC enable */
#define WM8978_R3_LEFT_DAC_ENABLE				(1 << 0)
#define WM8978_R3_RIGHT_DAC_ENABLE				(1 << 1)

/* Left or Right output channel mixer enable */
#define WM8978_R3_LEFT_MIX_ENABLE				(1 << 2)
#define WM8978_R3_RIGHT_MIX_ENABLE				(1 << 3)

/* ROUT2 or LOUT2 output enable */
#define WM8978_R3_ROUT2_OUT_ENABLE				(1 << 5)
#define WM8978_R3_LOUT2_OUT_ENABLE				(1 << 6)

/* OUT3 or OUT4 output enable */
#define WM8978_R3_OUT3_ENABLE					(1 << 7)
#define WM8978_R3_OUT4_ENABLE					(1 << 8)

/**********************************R4: WM8978_AUDIO_INTERFACE*****************************************/

/* Audio interface data format */
#define WM8978_R4_FMT_RIGHT_JUSTIFIED			(0 << 3)
#define WM8978_R4_FMT_LEFT_JUSTIFIED			(1 << 3)
#define WM8978_R4_FMT_I2S_FORMAT				(2 << 3)
#define WM8978_R4_FMT_PCM_MODE					(3 << 3)

/* Audio word length */
#define WM8978_R4_WORD_LEN_16_BITS				(0 << 5)
#define WM8978_R4_WORD_LEN_20_BITS				(1 << 5)
#define WM8978_R4_WORD_LEN_24_BITS				(2 << 5)
#define WM8978_R4_WORD_LEN_32_BITS				(3 << 5)

/**********************************R11~12: WM8978_DAC_DIGITAL_VOLUME*******************************************/

/* DAC Digital Volume Control */
#define WM8978_R11_12_DAC_VOL_MUTE				(0 << 0)
#define WM8978_R11_12_DAC_VOL_255				(0xFF << 0)

/* DAC left and DAC right volume donot update until a 1 is written to DACVU  */
#define  WM8978_R11_12_DACVU_ENABLE				(1 << 8)

/**********************************R14: WM8978_ADC_CONTROL*******************************************/

/* ADC left channel polarity adjust */
#define WM8978_R14_ADC_LEFT_POL_NORMAL			(0 << 0)
#define WM8978_R14_ADC_LEFT_POL_INVERT			(1 << 0)

/* ADC right channel polarity adjust */
#define WM8978_R14_ADC_RIGHT_POL_NORMAL			(0 << 1)
#define WM8978_R14_ADC_RIGHT_POL_INVERT			(1 << 1)

/* ADC oversample rate select */
#define WM8978_R14_ADC_SAMPLE_RATE_64			(0 << 3)
#define WM8978_R14_ADC_SAMPLE_RATE_128			(1 << 3)

/* High Pass Filter Enable */
#define WM8978_R14_HIGHT_FILTER_DISABLE			(0 << 8)
#define WM8978_R14_HIGHT_FILTER_ENABLE			(1 << 8)

/**********************************R15~16: WM8978_ADC_DIGITAL_VOLUME*********************************/

/* Left or Right ADC Digital Volume Control */
#define WM8978_R15_LEFT_ADC_VOL_0DB				(0xFF << 0)
#define WM8978_R16_RIGHT_ADC_VOL_0DB			(0xFF << 0)

/* ADC left and ADC right volume do not update until a 1 is written to ADCVU */
#define WM8978_R15_ADC_VOL_UPDATE_ENABLE		(1 << 8)
#define WM8978_R16_ADC_VOL_UPDATE_ENABLE		(1 << 8)

/**********************************R27: WM8978_NOTCH_FILTER_1****************************************/

/* Notch filter enable */
#define WM8978_R27_NOTCH_FILTER_DISABLE			(0 << 7)
#define WM8978_R27_NOTCH_FILTER_ENABLE			(1 << 7)

/**********************************R35: WM8978_NOISE_GATE********************************************/

/* Noise gate function enable */
#define WM8978_R35_ALC_NOISE_GAGE_DISABLE		(0 << 3)
#define WM8978_R35_ALC_NOISE_GAGE_ENABLE		(1 << 3)

/**********************************R43: WM8978_BEEP_CONTROL******************************************/

/* AUXR beep input enable or mute */
#define WM8978_R43_AUXR_BEEP_INPUT_MUTE			(0 << 0)
#define WM8978_R43_AUXR_BEEP_INPUT_ENABLE		(1 << 0)

/* AUXR input to ROUT2 inverter gain */
#define WM8978_R43_AUXR_BEEP_INPUT_VOL_6DB		(7 << 1)

/* Invert ROUT2 output */
#define WM8978_R43_INVERT_ROUT2_OUTPUT_ENABEL	(1 << 4)

/**********************************R44: WM8978_INPUT_CONTROL*****************************************/

/* Connect LIP pin to left channel input PGA positive terminal. */
#define WM8978_R44_LIP_CNT_INPUT_PGA			(1 << 0)

/* Connect LIN pin to left channel input PGA negative terminal. */
#define WM8978_R44_LIN_CNT_INPUT_PGA			(1 << 1)

/* Connect L2 pin to left channel input PGA positive terminal. */
#define WM8978_R44_L2_CNT_INPUT_PGA				(1 << 2)

/* Connect RIP pin to right channel input PGA amplifier positive terminal. */
#define WM8978_R44_RIP_CNT_INPUT_PGA			(1 << 4)

/* Connect RIN pin to right channel input PGA negative terminal. */
#define WM8978_R44_RIN_CNT_INPUT_PGA			(1 << 5)

/* Connect R2 pin to right channel input PGA positive terminal. */
#define WM8978_R44_R2_CNT_INPUT_PGA				(1 << 6)

/* Microphone Bias Voltage Control */
#define WM8978_R44_MIC_BIAS_VOL_CTRL_0_9		(0 << 8) // 0.9 * AVDD
#define WM8978_R44_MIC_BIAS_VOL_CTRL_0_6		(1 << 8) // 0.6 * AVDD

/**********************************R47: WM8978_LEFT_ADC_BOOST_CONTROL*********************************/

/* Controls the auxilliary amplifer to the left channel input boost stage */
#define WM8978_R47_AUX_LEFT_BOOST_DISABLE		(0 << 0)
#define WM8978_R47_AUX_LEFT_BOOST_N_12DB		(1 << 0)
#define WM8978_R47_AUX_LEFT_BOOST_N_9DB			(2 << 0)
#define WM8978_R47_AUX_LEFT_BOOST_N_6DB			(3 << 0)
#define WM8978_R47_AUX_LEFT_BOOST_N_3DB			(4 << 0)
#define WM8978_R47_AUX_LEFT_BOOST_P_0DB			(5 << 0)
#define WM8978_R47_AUX_LEFT_BOOST_P_3DB			(6 << 0)
#define WM8978_R47_AUX_LEFT_BOOST_P_6DB			(7 << 0)

#define WM8978_R47_L2_LEFT_BOOST_DISABLE		(0 << 4)
#define WM8978_R47_L2_LEFT_BOOST_N_12DB			(1 << 4)
#define WM8978_R47_L2_LEFT_BOOST_N_9DB			(2 << 4)
#define WM8978_R47_L2_LEFT_BOOST_N_6DB			(3 << 4)
#define WM8978_R47_L2_LEFT_BOOST_N_3DB			(4 << 4)
#define WM8978_R47_L2_LEFT_BOOST_P_0DB			(5 << 4)
#define WM8978_R47_L2_LEFT_BOOST_P_3DB			(6 << 4)
#define WM8978_R47_L2_LEFT_BOOST_P_6DB			(7 << 4)

/* Boost enable for left channel input PGA */
#define WM8978_R47_PGA_LEFT_BOOST_P_0DB			(0 << 8)
#define WM8978_R47_PGA_LEFT_BOOST_P_20DB		(1 << 8)

/**********************************R48: WM8978_RIGHT_ADC_BOOST_CONTROL*********************************/

/* Controls the auxilliary amplifer to the right channel input boost stage */
#define WM8978_R48_AUX_RIGHT_BOOST_DISABLE		(0 << 0)
#define WM8978_R48_AUX_RIGHT_BOOST_N_12DB		(1 << 0)
#define WM8978_R48_AUX_RIGHT_BOOST_N_9DB		(2 << 0)
#define WM8978_R48_AUX_RIGHT_BOOST_N_6DB		(3 << 0)
#define WM8978_R48_AUX_RIGHT_BOOST_N_3DB		(4 << 0)
#define WM8978_R48_AUX_RIGHT_BOOST_P_0DB		(5 << 0)
#define WM8978_R48_AUX_RIGHT_BOOST_P_3DB		(6 << 0)
#define WM8978_R48_AUX_RIGHT_BOOST_P_6DB		(7 << 0)

#define WM8978_R48_L2_RIGHT_BOOST_DISABLE		(0 << 4)
#define WM8978_R48_L2_RIGHT_BOOST_N_12DB		(1 << 4)
#define WM8978_R48_L2_RIGHT_BOOST_N_9DB			(2 << 4)
#define WM8978_R48_L2_RIGHT_BOOST_N_6DB			(3 << 4)
#define WM8978_R48_L2_RIGHT_BOOST_N_3DB			(4 << 4)
#define WM8978_R48_L2_RIGHT_BOOST_P_0DB			(5 << 4)
#define WM8978_R48_L2_RIGHT_BOOST_P_3DB			(6 << 4)
#define WM8978_R48_L2_RIGHT_BOOST_P_6DB			(7 << 4)

/* Boost enable for left channel input PGA */
#define WM8978_R48_PGA_RIGHT_BOOST_P_0DB		(0 << 8)
#define WM8978_R48_PGA_RIGHT_BOOST_P_20DB		(1 << 8)

/**********************************R49: WM8978_OUTPUT_CONTROL*****************************************/

/* Thermal Shutdown Enable */
#define WM8978_R49_THER_SHUTDOWN_DISABLE		(0 << 1)
#define WM8978_R49_THER_SHUTDOWN_ENABLE			(1 << 1)

/* Speaker gain */
#define WM8978_R49_SPEAKER_GAIN_N_1				(0 << 2) // DC = AVDD / 2
#define WM8978_R49_SPEAKER_GAIN_P_1_5			(1 << 2) // DC = 1.5 x AVDD / 2

/* OUT3 output gain */
#define WM8978_R49_OUT3_GAIN_N_1				(0 << 3) // DC = AVDD / 2
#define WM8978_R49_OUT3_GAIN_P_1_5				(1 << 3) // DC = 1.5 x AVDD / 2

/* OUT4 output gain */
#define WM8978_R49_OUT4_GAIN_N_1				(0 << 4) // DC = AVDD / 2
#define WM8978_R49_OUT4_GAIN_P_1_5				(1 << 4) // DC = 1.5 x AVDD / 2

/* Right DAC output to left output mixer */
#define WM8978_R49_RIGHT_DAC_TO_LEFT_MIXER		(1 << 5)

/* Left DAC output to right output mixer */
#define WM8978_R49_LEFT_DAC_TO_RIGHT_MIXER		(1 << 6)

/**********************************R50: WM8978_LEFT_MIXER_CONTROL************************************/

/* Left DAC output to left output mixer */
#define WM8978_R50_LEFT_DACL2LMIX				(1 << 0)

/* Left bypass path to left output mixer */
#define WM8978_R50_LEFT_BYPL2LMIX				(1 << 1)

/* Left bypass volume contol to output */
#define WM8978_R50_LEFT_BYPLMIXVOL_6DB			(7 << 2)

/* Left Auxilliary input to left channel output mixer */
#define WM8978_R50_LEFT_AUXL2LMIX				(1 << 5)

/* Aux left channel input to left mixer volume control */
#define WM8978_R50_LEFT_AUXLMIXVOL_6DB			(7 << 6)

/**********************************R51: WM8978_RIGHT_MIXER_CONTROL************************************/

/* Right DAC output to right output mixer */
#define WM8978_R51_RIGHT_DACL2LMIX				(1 << 0)

/* Right bypass path to right output mixer */
#define WM8978_R51_RIGHT_BYPL2LMIX				(1 << 1)

/* Right bypass volume contol to output */
#define WM8978_R51_RIGHT_BYPLMIXVOL_6DB			(7 << 2)

/* Right Auxilliary input to right channel output mixer */
#define WM8978_R51_RIGHT_AUXL2LMIX				(1 << 5)

/* Aux right channel input to right mixer volume control */
#define WM8978_R51_RIGHT_AUXLMIXVOL_6DB			(7 << 6)

/**********************************R56: WM8978_OUT3_MIXER_CONTROL************************************/

/* OUT4 mixer output to OUT3 */
#define WM8978_R56_OUT4_2OUT3_ENABLE			(1 << 3)

/**********************************R57: WM8978_OUT4_MIXER_CONTROL************************************/

/* Right DAC mixer to OUT4 */
#define WM8978_R57_RMIX2OUT4_ENABLE				(1 << 1)

/* Left DAC mixer to OUT4 */
#define WM8978_R57_LMIX2OUT4_ENABLE				(1 << 4)

uint8_t wm8978_Reset(void);
void wm8978_SetOUT1Volume(uint8_t _ucVolume);
void wm8978_SetMicGain(uint8_t _ucGain);
void wm8978_CfgAudioIF(uint16_t _usStandard, uint8_t _ucWordLen);
void wm8978_CfgAudioPath(uint16_t _InPath, uint16_t _OutPath);
uint8_t wm8978_Init(void);
extern void wm8978_PowerDown(void);
extern void Player_I2S_Stop(void);
extern void wm8978_SetOUT2Volume(uint8_t _ucVolume);
extern ret_code_t Player_I2S_Start(void);

#endif // __WM8978_H__

